﻿package cont;


import core.*;
import mess.*;


// ============================================================= Контакт-комната
public class ContRoom extends Cont {

// ======================================================= Глобальные переменные
//private MessPars messPars; // Объект разбивки на блоки

// Состояние
public RoomInfo info; // Информация о контакте
public boolean fActive = true; // Отображать при перелистывании

// Сообщения
private MessRoom mess[] = new MessRoom[Setting.MAX_ONSCREEN]; // Очередь сообщений
private int messF; // Указатель на первое сообщение
private int messP; // Указатель на следующее (свободное) сообщение в очереди
private int messL; // Указатель на последнее добавленное сообщение в очереди
private int messTot; // Общее количество сообщений в очереди
private int messSel; // Указатель на выделенное сообщение

// Разметка
private int displace; // Смещение первой строки
private int distAll; // Общая высота всех сообщений в точках
private int messDrawF; // Указатель на первое отрисовываемое сообщение
private int messDraw; // Указатель на текущее отрисовываемое сообщение
private int sel2up; // Расстояние от верха сообщений до верха выделенного, в точках
private int selOff; // Расстояние от верха выделенного до его точки, которая должна быть в центре экрана
private int selPtr; // Расстояние от верха сообщений до selOff (центра выделенного)


// Разное
public int colNick = 0x000000; // Цвет ника
public int colSch; // Номер цветовой схемы
private int textH; // Высота окна текстовых сообщений
private int textW; // Шырина окна текстовых сообщений
public String titText = "Комната"; // Заголовок комнаты


// =============================================================== Инициализация
public ContRoom(RoomInfo roomInfo) {

	super();
	this.info = roomInfo;
}


public ContRoom(byte[] source) {

	super();
	this.info = new RoomInfo();
	fromByte(source);
}


// ======================================================== Добавление сообщения
public int addMess(MessRoom newMess) {

	if ((newMess.res == null) && (textW > 0)) {
		newMess.parse(textW);
	}

	mess[messP] = newMess;
	//	distDown += newMess.hTot;
	distAll += newMess.hTot;

	// Расстановка указателей
	if (++messTot >= mess.length) {
		messTot = mess.length;
	}
	messL = messP;
	if (++messP >= mess.length) {
		messP = 0;
	}
	if (messP == messF) {
		// distDown -= mess[messF].hTot;
		distAll -= mess[messF].hTot;
		sel2up -= mess[messF].hTot;
		if (sel2up < 0) {
			sel2up = 0;
		}
		if (++messF >= mess.length) {
			messF = 0;
		}
		if (messP == messSel) {
			messSel = messF;
		}
		if (messP == messDrawF) {
			messDrawF = messF;
			displace = 0;
		}
	}

	newHeight();

	return messL;
}


// ==================================================== Очистка списка сообщений
public void clear() {

	for (int q = messTot - 1; q >= 0; --q) {
		mess[q] = null;
	}

	messF = 0;
	messP = 0;
	messL = 0;
	messTot = 0;
	messSel = 0;
	distAll = 0;
	displace = 0;
	sel2up = 0;
	selOff = 0; // Расстояние от верха выделенного до его точки, которая должна быть в центре экрана
	selPtr = 0; // Расстояние от верха сообщений до selOff (центра выделенного)
	messDrawF = 0; // Указатель на первое отрисовываемое сообщение

	System.gc();
}


// ======================================================== Предыдущий указатель
private int selPrev(int currentSel) {

	if (currentSel == messF) {
		return currentSel;
	} else {
		if (--currentSel < 0) {
			currentSel = mess.length - 1;
		}
		return currentSel;
	}
}


// ========================================================= Следующий указатель
private int selNext(int currentSel) {

	if (currentSel == messL) {
		return currentSel;
	} else {
		if (++currentSel >= mess.length) {
			currentSel = 0;
		}
		return currentSel;
	}
}


// ===================================================== Сдвинуть селектор вверх
public void selUp() {

	if (messTot > 0) {
		try {
			if ((selOff < (textH >> 1)) && messSel != messF) { // Можно селектировать предыдущее сообщение
				messSel = selPrev(messSel);
				sel2up -= mess[messSel].hTot;

				if (mess[messSel].hTot < textH) {
					selOff = mess[messSel].hTot >> 1;
				} else {
					selOff = mess[messSel].hTot - (textH >> 1);
				}
				newHeight();
			} else { // Селектор остается в пределах текущего сообщения
				selOff -= textH >> 1;
				if (selOff < 0) {
					selOff += textH >> 1;
				}
				newHeight();
			}

		} catch (Exception e) {
			Mess.err("ContRoom.selUp", "Ошибка смещения вниз", e);
		}
	}
}


// ====================================================== Сдвинуть селектор вниз
public void selDown() {

	if (messTot > 0) {

		try {

			if (((mess[messSel].hTot - selOff) < (textH >> 1)) && (messSel != messL)) { // Можно селектировать следующее сообщение
				sel2up += mess[messSel].hTot;
				messSel = selNext(messSel);
				if (mess[messSel].hTot < textH) {
					selOff = mess[messSel].hTot >> 1;
				} else {
					selOff = textH >> 2;
				}
				newHeight();
			} else { // Селектор остается в пределах текущего сообщения
				selOff += textH >> 1;
				if (selOff > mess[messSel].hTot) {
					selOff -= textH >> 1;
				}
				newHeight();
			}

		} catch (Exception e) {
			Mess.err("ContRoom.selDown", "Ошибка смещения вниз", e);
		}
	}
}


//===================================== Сдвинуть селектор на последнее сообщение
//private void selLast() {
//
//	if (textH > 0) {
//		messSel = messL;
//		if (mess[messSel].hTot < textH) {
//			selOff = mess[messSel].hTot >> 1;
//		} else {
//			selOff = mess[messSel].hTot - (textH >> 1);
//		}
//		sel2up = distAll - mess[messSel].hTot;
//		newHeight();
//	}
//}


// ======================================================= Задать цвет сообщения
public void setMessColor(int messNum, int color) {

	mess[messNum].color = color;
}


// =========================================================== Получить смещение
public int getDisplace() {

	return displace;
}


// ==================================== Получить первое отрисовываемое сообщение
public MessRoom getFirst() {

	messDraw = messDrawF;

	return mess[messDraw];
}


// ================================= Получить следующее отрисовываемое сообщение
public MessRoom getNext() {

	if (messDraw != messL) {
		if (++messDraw >= mess.length) {
			messDraw = 0;
		}
		return mess[messDraw];
	} else {
		return null;
	}
}


//================================================ Получить выделенное сообщение
public MessRoom getSel() {

	if (messTot > 0) {
		return mess[messSel];
	} else {
		return null;
	}
}


// ====================================================== Текущее селектировано?
public boolean isSel() {

	if (messDraw == messSel) {
		return true;
	} else {
		return false;
	}
}


// ================================================ Преобразование в байт-массив
public byte[] toByte() {

	ToBytes ser = new ToBytes(4096);
	ser.putInt(RoomInfo.NAME);
	ser.putString(name);
	return ser.getBytes();
}


//======================================================= Преобразовать в строку
public String toString() {

	return name + ", oneTot=" + info.oneTot + ", oneMen=" + info.oneMen
			+ ", oneWom=" + info.oneWom + ", right=" + info.right + ", birthDay="
			+ info.birthDay + "." + info.birthMon + "." + info.birthYear + ", descr="
			+ info.descr + ", mess=" + mess + ", rules=" + info.rules;
}


// ================================================== Заполнение из байт-массива
public void fromByte(byte[] content) {

	try {
		FromBytes ser = new FromBytes(content, 0);

		while (ser.pt < content.length) {
			int type = ser.readInt(); // Тип читаемого блока
			switch (type) {
				case RoomInfo.NAME:
					name = ser.readString();
					break;
				case RoomInfo.DESCR:
					info.descr = ser.readString();
					break;
				case RoomInfo.RULES:
					info.rules = ser.readString();
					break;
				case RoomInfo.ONE_ALL: // Кол-во подключенных сейчас контактов (сводная)
					info.oneTot = ser.readInt();
					info.oneMen = ser.readInt();
					info.oneWom = ser.readInt();
					break;
				case RoomInfo.ONE_TOT: // Кол-во подключенных сейчас контактов
					info.oneTot = ser.readInt();
					break;
				case RoomInfo.ONE_MEN: // Кол-во подключенных сейчас контактов
					info.oneMen = ser.readInt();
					break;
				case RoomInfo.ONE_WOM: // Кол-во подключенных сейчас контактов
					info.oneWom = ser.readInt();
					break;
				case RoomInfo.MESS:
					info.mess = ser.readString();
					break;
				default:
					Mess.err("RoomInfo.unserialize", "Неизвестный тип записи: " + type);
			}
		}
	} catch (Exception e) {
		Mess.err("RoomInfo.unserialize", "Ошибка заполнения инфо из байт-массива",
				e);
	}

}


//============================================== Вычислить первое отрисовываемое
private void setFirst() {

	messDrawF = messSel;
	int messH = selOff;

	// Вычисляем первое отрисовываемое
	int scrHalf = textH >> 1;
	while (messH < scrHalf) {
		messDrawF = selPrev(messDrawF);
		messH += mess[messDrawF].hTot;
	}
	// messDrawF актуален

	displace = scrHalf - messH;
}


//============================================== Вычислить первое отрисовываемое
private void setFirstDown() {

	messDrawF = messL;
	int messH = mess[messDrawF].hTot;

	// Вычисляем первое отрисовываемое
	while (messH < textH) {
		messDrawF = selPrev(messDrawF);
		messH += mess[messDrawF].hTot;
	}
	// messDrawF актуален

	displace = textH - messH;
}


//============================================= Пересчет высоты блоков сообщений
private void newHeight() {

	selPtr = sel2up + selOff;
	int scrHalf = textH >> 1;

	if (selPtr <= scrHalf) { // Выделенное близко к верху
		displace = 0; // Смещение первой строки
		messDrawF = messF; // Указатель на первое отрисовываемое сообщение
	} else if ((distAll - selPtr) < scrHalf) { // Выделенное близко к низу
		setFirstDown();
	} else { // Выделенное посреди экрана
		setFirst();
	}
}


// =================================================== Пересчет блоков сообщений
public void setSize(int width, int height) {

	if (textW != width) {
		textW = width;
		textH = height;
		distAll = 0;
		sel2up = 0;
		synchronized (Man.main) {
			//			messPars.setWidth(width);
			if (messTot > 0) {
				int h;
				boolean fUpper = true;

				for (int q = messTot - 1; q >= 0; --q) {
					mess[q].parse(textW);
					h = mess[q].hTot;
					distAll += h; // Общая высота всех сообщений в точках
					if (q == messL) {
						fUpper = false;
					}
					if (fUpper) {
						sel2up += h;
					}
					if (q == messSel) {
						fUpper = true;
					}
				}
				// distAll и sel2up актуальны
				newHeight();
			}
		}
	} else if (textH != height) {
		textH = height;
		newHeight();
	}
}


}
